package com.netease.demo.shortvideo.uploader;

import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.widget.Toast;

import com.netease.demo.shortvideo.DemoCache;
import com.netease.demo.shortvideo.model.VideoItem;
import com.netease.demo.shortvideo.server.DemoServerHttpClient;
import com.netease.demo.shortvideo.server.entity.AddVideoResponseEntity;
import com.netease.demo.shortvideo.server.entity.VideoInfoEntity;
import com.netease.demo.shortvideo.uploader.constant.UploadState;
import com.netease.demo.shortvideo.uploader.model.UploadDataAccessor;
import com.netease.demo.shortvideo.uploader.model.UploadDbHelper;
import com.netease.demo.shortvideo.util.network.NetworkChangeBroadcastReceiver;
import com.netease.demo.shortvideo.util.network.NetworkUtils;

import java.util.ArrayList;
import java.util.List;


/**
 * Created by zhukkun on 2/22/17.
 */
public class UploadController extends BaseUiController<UploadController.UploadUi> {
    public static final String TAG = "uploadtest";

    private UploadService.UploadBinder mBinder;
    boolean mBound = false;
    private int uploadState = UploadState.STATE_WAIT;

    private UploadDataAccessor dataAccessor = new UploadDataAccessor();
    private Handler handler;

    private AlertDialog MobileNetworkDialog; //移动网络的提示框
    private boolean needResumeUpload; //是否需要恢复上传
    private boolean allowMobileNetwork = false; //是否允许移动网络进行上传
    private boolean needToAlert = true;

    NetworkChangeBroadcastReceiver receiver = new NetworkChangeBroadcastReceiver(new NetworkChangeBroadcastReceiver.NetworkChangeCallBack() {
        @Override
        public void onNetworkChanged(boolean connected, int type) {
            Log.d(TAG, "NeedResume:" + needResumeUpload + ",con:" + connected + ",type:" + type + ",allow mobile:" + allowMobileNetwork);
            if(needResumeUpload){
                if(connected){
                    startUploadIfAllow();
                }
            }else if(mBound && mBinder.isUploading() && !allowMobileNetwork && type == NetworkUtils.TYPE_MOBILE ){
                mBinder.stopUpload();
                needResumeUpload = true;
                Toast.makeText(mContext.getApplicationContext(), "已切换至蜂窝网络, 暂停上传", Toast.LENGTH_SHORT).show();
                startUploadIfAllow();
            }

        }
    });

    @Override
    protected void onUiAttached(UploadUi ui) {

    }

    @Override
    protected void populateUi(UploadUi ui) {
        ui.updateAllItems();
        ui.updateUploadState(uploadState);
    }

    @Override
    protected void onUiDetached(UploadUi ui) {

    }

    @Override
    public void handleIntent(Intent intent) {

    }

    @Override
    protected void onInit() {
        handler = new Handler(Looper.getMainLooper());
        dataAccessor.addObserver(new UploadDataAccessor.DataChangeObserver() {

            @Override
            public void onDataSetChanged(final List<VideoItem> data) {
                startUploadIfAllow();

                UploadUi ui = mUi;
                if(ui != null){
                    ui.onDataSetChanged(data);
                }else{
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            onDataSetChanged(data);
                        }
                    }, 200);
                }
            }
        });

        new Thread(new Runnable() {
            @Override
            public void run() {
                final List<VideoItem> items = UploadDbHelper.getUploadListFromDb();
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                       getDataAccessor().addLocalVideoItems(items);
                    }
                });
            }
        }).start();

        receiver.registReceiver(mContext);

    }

    @Override
    protected void onSuspend() {
        unbindService();
        receiver.unregist(mContext);
    }

    public interface UiCallBack{
        /**
         *
         * @param totalCount 请求完云端数据后, 本地加云端的总量
         */
        void onReceived(int totalCount);
    }

    /**
     * 从云端获取数据
     * @param callBack
     */
    public void getCloudVideoData(@Nullable final UiCallBack callBack) {

        if(mUi!=null){
            mUi.showLoading(true);
        }

        DemoServerHttpClient.getInstance().videoInfoGet(null, new DemoServerHttpClient.DemoServerHttpCallback<List<VideoInfoEntity>>() {
            @Override
            public void onSuccess(List<VideoInfoEntity> videoInfoEntities) {
                if(mUi!=null){
                    mUi.showLoading(false);
                }
                List<VideoItem> videoItems= new ArrayList<VideoItem>();
                for (int i = 0; i < videoInfoEntities.size(); i++) {
                    VideoInfoEntity entity = videoInfoEntities.get(i);

                    VideoItem videoItem = dataAccessor.acquireByVid(entity.getVid());
                    if(videoItem !=null && videoItem.getId().startsWith("local")){
                        dataAccessor.removeItem(videoItem);
                    }

                    videoItem = new VideoItem();
                    videoItem.setEntity(entity);
                    videoItems.add(videoItem);
                }
                getDataAccessor().setCloudVideoItems(videoItems);

                if(getDataAccessor().getTranscodingVidList()!=null && getDataAccessor().getTranscodingVidList().size()>0){
                    if(!mBound) {
                        bindService();
                    }
                }
                if(callBack!=null){
                    callBack.onReceived(dataAccessor.getTotalCount());
                }
            }

            @Override
            public void onFailed(int code, String errorMsg) {
                if(mUi!=null){
                    mUi.showLoading(false);
                }

                if(callBack!=null){
                    callBack.onReceived(dataAccessor.getTotalCount());
                }
            }
        });
    }

    public void startUploadIfAllow() {
        if (!getDataAccessor().isFullySuccess() && getDataAccessor().hasWaitTask()) {

            if (!allowMobileNetwork && NetworkUtils.getNetworkType() == NetworkUtils.TYPE_MOBILE) {

                if(!needToAlert) return;

                needResumeUpload = true;
                try {
                    //Context传入DemoCache.getVisibleActivity(), 则在其他页面也可弹窗提示
                    AlertDialog.Builder builder = new AlertDialog.Builder(DemoCache.getVisibleActivity() == null ? mContext : DemoCache.getVisibleActivity());
                    builder.setMessage("正在使用手机流量上传, 是否继续?");
                    builder.setPositiveButton("是",
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    allowMobileNetwork = true;
                                    startUpload();
                                }
                            });
                    builder.setNegativeButton("否",
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    //若提示且用户不上传, 则依赖后续网络切换至WIFI自动上传
                                    allowMobileNetwork = false;
                                    needToAlert = false;
                                    Toast.makeText(mContext.getApplicationContext(), "待连接至WIFI网络后,继续上传", Toast.LENGTH_SHORT).show();
                                    dialog.dismiss();

                                }
                            });
                    builder.setCancelable(false);

                    if(MobileNetworkDialog == null || !MobileNetworkDialog.isShowing()){
                        MobileNetworkDialog = builder.show();
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                startUpload();

                //4G弹窗时, 切换到WIFI的情况
                if(MobileNetworkDialog!=null && MobileNetworkDialog.isShowing()){
                    MobileNetworkDialog.dismiss();
                    Toast.makeText(mContext.getApplicationContext(), "已连接至WIFI网络, 继续上传", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }

    public void startUpload(){
        if(!mBound) {
            bindService();
        }else{
            mBinder.startUpload();
        }
        needResumeUpload = false;
    }

    private void bindService(){
        Intent intent = new Intent(mContext, UploadService.class);
        mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    private void unbindService(){
        if(mBound) {
            mContext.unbindService(mConnection);
        }
    }

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mBinder = (UploadService.UploadBinder) service;
            mBinder.attachController(UploadController.this);
            mBound = true;
            //由于有两处绑定server的入口,所以绑定成功后,再次判断网络后,再开启上传任务
            startUploadIfAllow();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mBound = false;
        }
    };

    public void onReceiveUploadCallback(final String id, final int progress, final int state) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (state == UploadState.STATE_UPLOAD_FAIL && (receiver.justNetworkChanged() || !NetworkUtils.isNetworkConnected(false))) {
                    //进到此分支,为网络中断造成失败,故停止上传,避免后续任务继续失败
                    if(mBound){
                        mBinder.stopUpload();
                    }
                    needResumeUpload = true;

                    if(!NetworkUtils.isNetworkConnected(false)) {
                        Toast.makeText(mContext.getApplicationContext(), "网络异常, 恢复后将继续上传", Toast.LENGTH_SHORT).show();
                    }else if(NetworkUtils.getNetworkType() == NetworkUtils.TYPE_MOBILE){
                        Toast.makeText(mContext.getApplicationContext(), "已切换至蜂窝网络, 暂停上传", Toast.LENGTH_SHORT).show();
                    }
                } else {
                    if (mUi != null) {
                        mUi.updateItemProgress(id, progress, state);
                    }
                }
            }
        });
    }

    public void onUploadStateChanged(final int state) {
        uploadState = state;

        final UploadUi ui = mUi;
        if(ui!=null) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    ui.updateUploadState(state);
                }
            });
        }
    }

    public void onAddVideoResult(final int code, final String id, final AddVideoResponseEntity addVideoResponseEntity) {
        if (mUi != null) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    mUi.onAddVideoResult(code, id, addVideoResponseEntity);
                }
            });
        }
    }

    public UploadDataAccessor getDataAccessor() {
        return dataAccessor;
    }


    public void deleteUploadItem(VideoItem videoItem) {
        if(mBound && mBinder!=null){
            mBinder.deleteUploadItem(videoItem);
        }
        //由于可能存在4G网络下未绑定上传服务的情况, 所以删除数据需要放在条件语句外
        getDataAccessor().removeItem(videoItem);
    }

    public interface UploadUi extends Ui {

        void updateAllItems();

        void updateUploadState(int state);

        void updateItemProgress(String id, int progress, int state);

        Context getContext();

        void showLoading(boolean show);

        void onDataSetChanged(List<VideoItem> data);

        void onAddVideoResult(int code, String id, AddVideoResponseEntity addVideoResponseEntity);
    }

}
